#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include "rf.h"
#include "string.h"
#include "protocol.h"
#include "stream_buffer.h"
#include "4g_app.h"
#include "semphr.h"
/*


sector 0 :  boot                0x08000000 0x08003fff 16K
sector 1 :  param1              0x08004000 0x08007fff 16K
sector 2 :  param2              0x08008000 0x0800bfff 16K
sector 3 :  param3              0x0800c000 0x0800ffff 16K
sector 4 :  param4              0x08010000 0x0801ffff 64K
sector 5-6: app                 0x08020000-0x0805ffff 128k+128k
sector 7-8: ap_firmware         0x08060000 0x0809ffff 128k+128k
sector 9 :  sensor_firmware     0x080a0000 0x080bffff 128k
sector 10:  io_firmware         0x080c0000 0x080dffff 128k
sector 11:  io_firmware         0x080e0000 0x080fffff 128k

*/






extern struct_sensor_list sensor_list[];
extern unsigned short crc16(unsigned short crc, unsigned char const *buffer,int len);
extern void debug(const char* pstr);

extern StreamBufferHandle_t client_need_send_data[];
extern char debug_str[1024];
extern struct_etc_4g_timer_data sensor_4g_timer_data[];           //定时数据

struct_ap_param g_ap_param;

const uint32_t flash_begin[3] = {0,FLASH_AP_FIRMWARE_BEGIN,FLASH_SENSOR_FIRMWARE_BEGIN};

FW_HEADER_t_5xx pheader_5xx;



//把flash中的参数 读取到ram中
void read_sys_param_from_flash(uint32_t flash_addr)
{
    struct_sys_param * p_to_flash_sys_param = (struct_sys_param *)flash_addr;
    uint8_t i=0;

    g_ap_param = p_to_flash_sys_param->ap_param;
    for(i=0;i<g_ap_param.sensor_count;i++)
    {
        if(i>=SENSOR_MAX_COUNT) 
            break;  
        memcpy(&sensor_list[i].sensor_id,&p_to_flash_sys_param->sensor_cfg_4g[i],sizeof(struct_sensor_cfg_4g));
    }
	
	read_firmware_sensor_head();
	g_ap_param.ap_version = AP_VERSION;
	if(memcmp(&g_ap_param,&(p_to_flash_sys_param->ap_param),sizeof(g_ap_param)) != 0)
	{
		for(i=0;i<5;i++){
			if(0==save_sys_param_to_flash(FLASH_PARAM1,FLASH_SECTOR_1))
				break;
		}
		for(i=0;i<5;i++){
			if(0==save_sys_param_to_flash(FLASH_PARAM2,FLASH_SECTOR_2))
				break;
		}		
	}
}

//把sys_param 和 sensorlist分别保存到指定Flash中
int8_t save_sys_param_to_flash(uint32_t flash_addr,uint8_t sector_num)
{
    struct_sys_param * p_to_flash_sys_param = NULL;
    uint16_t len;
    uint16_t crc;
    uint8_t *p_data;
    uint8_t i,j;
    uint32_t addr;
	FLASH_EraseInitTypeDef EraseInit;
	uint32_t SectorError	;
	
    HAL_FLASH_Unlock();
	
	EraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
	EraseInit.Banks = FLASH_BANK_1;
	EraseInit.NbSectors = 1;
	EraseInit.Sector = sector_num;
	EraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;
	HAL_FLASHEx_Erase(&EraseInit,&SectorError);

	g_ap_param.crc = 0xffff;
	p_data = (uint8_t *)&g_ap_param;
	for(i=0;i<sizeof(g_ap_param);i++)
	{
        addr = flash_addr+i;
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,addr,p_data[i]);
        if(*((uint8_t *)addr) != p_data[i])
        {
            HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,addr,p_data[i]);
            if(*((uint8_t *)addr) != p_data[i])
                return -1;
        }
	}


	for(i=0;i<g_ap_param.sensor_count;i++)
	{
        p_data = (uint8_t *)&sensor_list[i];
	    for(j=0;j<sizeof(sensor_list[0].sensor_cfg)+2;j++)
	    {        
            addr = flash_addr+sizeof(struct_ap_param)+i*(sizeof(sensor_list[i].sensor_cfg)+2)+j;
		    HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,addr,p_data[j]);
            if(*((uint8_t *)addr) != p_data[j])
            {
                HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,addr,p_data[j]);
                if(*((uint8_t *)addr) != p_data[j])
                    return -1;
            }
        }
	}

    len = sizeof(struct_ap_param) - 2 + g_ap_param.sensor_count * sizeof(struct_sensor_cfg_4g);    
    crc = crc16(0,(uint8_t *)(flash_addr+2),len);
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,flash_addr,crc);  
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,flash_addr+1,crc>>8);
    p_to_flash_sys_param = (struct_sys_param * )(flash_addr);
    if(crc == p_to_flash_sys_param->ap_param.crc)    
    {
        g_ap_param.crc = crc;
        return 0;
    }
    else
    {
        return -1;
    }
      
}

// 初始化系统参数，如果flash有参数 则读取到ram中  如果flash没有参数 初始化默认参数
void init_sys_param(void)
{
    struct_sys_param * p_to_flash_sys_param = NULL;
    uint8_t i = 0;
    const uint32_t flash_addr[] = {FLASH_PARAM1,FLASH_PARAM2};
    uint16_t len;
    uint16_t crc;

    for(i=0;i<2;i++) //flash to ram
    {
        p_to_flash_sys_param = (struct_sys_param * )flash_addr[i];
        if(p_to_flash_sys_param->ap_param.code == FLASH_CODE)
        {
            len = sizeof(struct_ap_param) - 2 + p_to_flash_sys_param->ap_param.sensor_count * sizeof(struct_sensor_cfg_4g);
            crc = crc16(0,(uint8_t *)&p_to_flash_sys_param->ap_param.code,len);
            if(crc == p_to_flash_sys_param->ap_param.crc)
            {
                read_sys_param_from_flash(flash_addr[i]);
                return;
            }
        }
    }
    //flash param error
    g_ap_param.crc = 0xffff;
    g_ap_param.code = FLASH_CODE;
    g_ap_param.ap_id = *(uint32_t *)0x0800001c;
		if(g_ap_param.ap_id == 0)
			g_ap_param.ap_id = 0x20201001;
    g_ap_param.on_delay = 0;
    g_ap_param.off_to_on_min_time = 400;
    g_ap_param.ip_port_param[0].ip = (219<<24) | (239<<16) | (83<<8) | (74);
    g_ap_param.ip_port_param[0].port = 40010;    
    g_ap_param.ip_port_param[0].realtime_data_switch = 0;
    g_ap_param.ip_port_param[0].timer_data_switch = 1;
    g_ap_param.ip_port_param[0].timer_data_switch = 1;   
    g_ap_param.ip_port_param[0].timer_data_time_sec = 60;

    for(i=0;i<5;i++){
        if(0==save_sys_param_to_flash(FLASH_PARAM1,FLASH_SECTOR_1))
            break;
    }
    for(i=0;i<5;i++){
        if(0==save_sys_param_to_flash(FLASH_PARAM2,FLASH_SECTOR_2))
            break;
    }
}



void erase_ap_firm_flash()
{
	FLASH_EraseInitTypeDef EraseInit;
	uint32_t SectorError	;
	__disable_irq() ;  //关总中断
	HAL_FLASH_Unlock();
	EraseInit.Sector = FLASH_SECTOR_7;
	EraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
	EraseInit.Banks = FLASH_BANK_1;
	EraseInit.NbSectors = 2;		
	EraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;
	HAL_FLASHEx_Erase(&EraseInit,&SectorError);
	__enable_irq() ; //开总中断	
}

void erase_sensor_firm_flash()
{
	FLASH_EraseInitTypeDef EraseInit;
	uint32_t SectorError	;
	__disable_irq() ;  //关总中断
	HAL_FLASH_Unlock();
	EraseInit.Sector = FLASH_SECTOR_9;
	EraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
	EraseInit.Banks = FLASH_BANK_1;
	EraseInit.NbSectors = 1;		
	EraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;
	HAL_FLASHEx_Erase(&EraseInit,&SectorError);
	__enable_irq() ; //开总中断	
}

uint32_t find_firm_is_ap_or_sensor(char *file_name)
{
	uint32_t i = 0;
	
	while(file_name[i] != 0 && i<64)
	{
		if(file_name[i] == 'n' && file_name[i+1] == '1')
			return FIRM_AP;
		if(file_name[i] == 's' && file_name[i+1] == 'e'&& file_name[i+2] == 'n'&& file_name[i+3] == 's'&& file_name[i+4] == 'o')
			return FIRM_SENSOR;
		i++;
	}
	return 0;
}


/*
固件存储方式：[4bytes(固件地址)1bytes(行校验)32bytes(固件内容) ] X (n行)

*/
void read_firmware_sensor_head()
{
	unsigned char * begin_addr = (unsigned char * )FLASH_SENSOR_FIRMWARE_BEGIN;
	uint16_t i,j;
	uint32_t check_bytes_add = 0;
	uint16_t lines_size = 0;
	uint8_t *p_data;
	static uint32_t last_addr = 0;
	uint32_t addr = 0;
	
	for(i=0;i<5;i++)  //读取固件头
	{
		memcpy((uint8_t *)((uint32_t)&pheader_5xx+i*32),begin_addr+i*37+5,32);
	}
	
	if(pheader_5xx.ulId != 0xdada10af || pheader_5xx.ucCfgComb != 3)
	{
		g_ap_param.sensor_firmware_software_version = FIRM_HEAD_ERROR;	
		return;
	}
	
	begin_addr += 37*8;
	lines_size = pheader_5xx.uiFwSize/32;
	
	for(i=0;i<lines_size;i++)
	{
		p_data = begin_addr+i*37;  //指向每行的起始地址
		for(j=5;j<37;j++)
		{
			check_bytes_add +=p_data[j];
		}
		addr = *((uint32_t *)p_data);
		if(addr == last_addr)
		{
			check_bytes_add = 0;
			break;
		}
		last_addr = addr;				
	}
	if(check_bytes_add == pheader_5xx.ulCheckSum)
	{
		g_ap_param.sensor_firmware_software_version =  pheader_5xx.uiFwVer;		
	}
	else
	{
		g_ap_param.sensor_firmware_software_version = FIRM_HEAD_ERROR;	
	}
}

HAL_StatusTypeDef sd;
int32_t write_bin_flash(uint32_t address,uint8_t *pdata,uint32_t size)
{
	int i = 0;
	uint8_t *p_readdata = (uint8_t *)address;
	uint8_t re_write_times = 0;
	
	if(address < 0x08004000)
		return -1;
	
__disable_irq() ;  //关总中断
	HAL_FLASH_Unlock();
	

	for(i=0;i<size;i++)
	{
		
		sd = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,address+i,pdata[i]);
		if(p_readdata[i] != pdata[i] )
		{
			if(re_write_times<2)
			{
				re_write_times++;
				i--;
				continue;
			}
			return -1;		
		}
	}	
	
	HAL_FLASH_Lock();
	__enable_irq() ; //开总中断		
	for(i=0;i<size;i++)
	{
		if(p_readdata[i] != pdata[i])
			return -1;
	}
	
	return 0;
}


void rev_4g_server_ap_firmware(int32_t whitch_client,uint8_t *pdata, uint16_t p_count,uint16_t p_seq,int16_t len)
{
	struct_gprs_4g_firmware_data *p_firmware = (struct_gprs_4g_firmware_data *)pdata;
	static uint32_t now_firmware_len = 0;   //记录当前flash写了的固件长度
	static uint16_t now_seq = 0xffff;   //记录当前flash写了的固件长度
	static uint16_t get_crc = 0;  //服务器下发的文件crc
	static char file_name[64];  //文件名
	static int8_t ap_or_sensor = 0;
	FLASH_EraseInitTypeDef EraseInit;
	uint32_t SectorError	;
	uint16_t crc;

	extern uint32_t timer_reboot_system;
	if(p_seq == 0)  //服务器下发第0包   如果本地不是第0包 则需要执行Flash擦除
	{
		now_firmware_len = 0;		
		memcpy(file_name,&pdata[2],len-2);
		file_name[len-2] = 0;
		get_crc = pdata[0]  | (pdata[1]<<8);
		ap_or_sensor = find_firm_is_ap_or_sensor(file_name);
		if(now_seq != 0) //本地记录不是第0包  需要执行擦除 如果本地已经是第0包 说明已经擦除过了 不操作
		{
			now_seq = 0;
			now_firmware_len = 0;
			if(ap_or_sensor == FIRM_AP)
				erase_ap_firm_flash();	
			else if(ap_or_sensor == FIRM_SENSOR)
				erase_sensor_firm_flash();			
		}
		send_4g_firmware_ack(whitch_client,p_count,now_seq+1,file_name);	
		sprintf(debug_str,"4g send :client_%d rev firmware_%s [%d->%d]\r\n",whitch_client, file_name,p_count,now_seq);
		debug(debug_str);				
	}
	
	if(p_seq == (now_seq+1) && p_seq <=p_count)  //服务器下发的固件位置等于本地记录的位置  才会写flash
	{
		if(len < 1500)
		{
			if(write_bin_flash(flash_begin[ap_or_sensor]+now_firmware_len,pdata,len) == 0) //写正确
			{
				now_firmware_len += len;
				now_seq = p_seq;

				send_4g_firmware_ack(whitch_client,p_count,now_seq+1,file_name);	
				sprintf(debug_str,"4g send :client_%d rev firmware_%s [%d->%d]\r\n",whitch_client, file_name,p_count,now_seq);
				debug(debug_str);			
		
			}
			else
			{
				now_firmware_len = 0;
				now_seq = 0;
				erase_ap_firm_flash();	
				erase_sensor_firm_flash();					
			}			
		}
	}
	
	if(p_count == now_seq)
	{
		crc = crc16(0,(uint8_t *)flash_begin[ap_or_sensor],now_firmware_len);
		if(crc == get_crc)
		{
			if(ap_or_sensor == FIRM_AP)
			{
				write_bin_flash(FLASH_AP_FIRMWARE_HEAD,(uint8_t *)&now_firmware_len,4);
				write_bin_flash(FLASH_AP_FIRMWARE_HEAD+4,(uint8_t *)&crc,2);
				timer_reboot_system = unix_second  + 10;
			}
			else if(ap_or_sensor == FIRM_SENSOR)
			{
				read_firmware_sensor_head();
			}
		}
	}	
	
}


void send_4g_firmware_ack(int32_t whitch_client,uint16_t p_count,uint16_t now_seq,void*file_name)
{
    uint8_t data[32];

    struct_firmware_ack *p_fa = (struct_firmware_ack *)data;

	p_fa->packet_head.head = PROTOCOL_HEAD;
	p_fa->packet_head.ap_id = g_ap_param.ap_id;
	p_fa->packet_head.len = 2;
	p_fa->packet_head.cmd1 = 0xc2;
	p_fa->packet_head.cmd2 = 0x02;
	p_fa->packet_seq = now_seq;
	p_fa->crc = crc16(0,data,sizeof(struct_firmware_ack)-2);

    if(xStreamBufferSpacesAvailable(client_need_send_data[whitch_client]) > sizeof(struct_firmware_ack))
    {					
        xStreamBufferSend(client_need_send_data[whitch_client],data,sizeof(struct_firmware_ack),10);
        xSemaphoreGive( client_task_flag[whitch_client].other_data_send_enable);
    }
    else
    {
        debug("4g send: other data write buff error  ...no space\r\n");
    }

}


void rev_4g_updata_sensor_list(int32_t whitch_client,struct_gprs_4g_updata_sensor_data *pdata)
{
	struct_gprs_4g_updata_sensor_data *p_sensor_list = pdata;
	uint8_t i,index;
	struct_to_4g_ack_no_data to_4g_ack_no_data;

	
	sprintf(debug_str,"4g get: updata_sensor list %d[",p_sensor_list->sensor_count);
	debug(debug_str);
	for(i=0;i<p_sensor_list->sensor_count;i++)
	{
		index = find_sensor_index(p_sensor_list->sensor_id[i]); //找到索引
		if(index < SENSOR_MAX_COUNT)
		{
			sensor_list[index].enable_updata = ENABLE_UPDATA;
			sprintf(debug_str,"%04X ",p_sensor_list->sensor_id[i]);
			debug(debug_str);
		}
	}
	debug("]\r\n");

	if(g_ap_param.sensor_firmware_software_version != FIRM_HEAD_ERROR && g_ap_param.sensor_firmware_software_version != FIRM_LINES_ERROR &&
		g_ap_param.sensor_firmware_software_version != 0xffff)
	{
		sensor_firmware_updata_manage.start_time = get_unix_time();
		sensor_firmware_updata_manage.resend_times = 0;
		sensor_firmware_updata_manage.control_flag = 1;
		to_4g_ack_no_data.packet_head.cmd2 = 0x02;
	}
	else
	{
		to_4g_ack_no_data.packet_head.cmd2 = 0xf2;
	}
	
	to_4g_ack_no_data.packet_head.head = PROTOCOL_HEAD;
	to_4g_ack_no_data.packet_head.ap_id = g_ap_param.ap_id;
	to_4g_ack_no_data.packet_head.len = 0;
	to_4g_ack_no_data.packet_head.cmd1 = 0xc3;

	to_4g_ack_no_data.crc = crc16(0,(const uint8_t *)&to_4g_ack_no_data,sizeof(struct_to_4g_ack_no_data)-2);

    if(xStreamBufferSpacesAvailable(client_need_send_data[whitch_client]) > sizeof(to_4g_ack_no_data))
    {					
        xStreamBufferSend(client_need_send_data[whitch_client],&to_4g_ack_no_data,sizeof(to_4g_ack_no_data),10);
        xSemaphoreGive( client_task_flag[whitch_client].other_data_send_enable);
    }
    else
    {
        debug("4g send: other data write buff error  ...no space\r\n");
    }
}